﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

namespace Bamboo.Excel
{
    public class ListToExcel
    {
        public class ColumnInfoEx
        {
            public string FieldName;
            public string ColumnName = "";
            public int Width = -1;
            public bool Valid = true;
        }

        private XSSFWorkbook _workbook;

        private Dictionary<string, ColumnInfoEx> _exdict = new Dictionary<string, ColumnInfoEx>();

        public ListToExcel()
        {
            _workbook = new XSSFWorkbook();
        }

        public void SetColumnExInfo(string fieldName, string columnName, int width = -1, bool valid = true)
        {
            ColumnInfoEx v;
            if (!_exdict.TryGetValue(fieldName, out v))
            {
                v = new ColumnInfoEx();
                v.FieldName = fieldName;
                _exdict.Add(fieldName, v);
            }
            v.ColumnName = columnName;
            v.Width = width;
            v.Valid = valid;
        }

        public void ClearColumnInfoEx()
        {
            _exdict.Clear();
        }

        public void Save(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Create))
            {
                _workbook.Write(fs);
            }
        }


        public void WriteSheet<T>(string sheetName, IEnumerable<T> objectList)
            where T : class
        {
            var sheet = _workbook.CreateSheet(sheetName);
            int rowIndex = sheet.PhysicalNumberOfRows;
            Type objectType = typeof(T);
            var columns = Bamboo.Utils.SerializeFieldInfo.Parse(objectType);
            //删除用户要求忽略的字段
            foreach (var item in _exdict.Values)
            {
                if (!item.Valid) columns.RemoveAll(a => a.MemberInfo.Name == item.FieldName);
            }
            sheet.DefaultRowHeight = 400;
            //写入首行标题
            if (rowIndex == 0)
            {
                List<string> colNames = new List<string>(32);
                List<int> colWidths = new List<int>(32);
                for (int index = 0; index < columns.Count; ++index)
                { 
                    var column = columns[index];
                    string name = column.Name();
                    int width = Encoding.Default.GetBytes(name).Length;
                    //覆盖配置
                    ColumnInfoEx exinfo = null;
                    if (_exdict.TryGetValue(column.MemberInfo.Name, out exinfo))
                    {
                        if (!exinfo.Valid) continue; //忽略这个字段，不导出
                        if (!string.IsNullOrWhiteSpace(exinfo.ColumnName)) name = exinfo.ColumnName;
                        if (exinfo.Width > 0) width = exinfo.Width;
                    }
                    colNames.Add(name);
                    colWidths.Add(width);
                }
                sheet.SetColumnsWidth(colWidths.ToArray());
                sheet.AddRow(rowIndex++, colNames.ToArray());
            }
            //写入每一行数据
            foreach (T obj in objectList)
            {
                var row = sheet.AddRow(rowIndex++);
                for (int columnIndex = 0; columnIndex < columns.Count; ++columnIndex)
                {
                    var column = columns[columnIndex];
                    var fieldtype = column.FieldType().Name.ToLower();
                    if (column.IsNumericType)
                    {
                        object valueObject = column.GetValue(obj);
                        string valueString = (valueObject != null) ? valueObject.ToString() : "0";
                        double valueDouble = double.Parse(valueString);
                        XSSFCell cell = row.CreateCell(columnIndex, CellType.Numeric) as XSSFCell;
                        cell.SetCellValue(valueDouble);
                    }
                    else
                    {
                        object valueObject = column.GetValue(obj);
                        string valueString = (valueObject != null) ? valueObject.ToString() : "";
                        XSSFCell cell = row.CreateCell(columnIndex, CellType.String) as XSSFCell;
                        cell.SetCellValue(valueString);
                    }
                }
            }
        }

    }
}
